package com.atguigu.gulimall.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.common.utils.HttpUtils;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.gulimall.member.dao.MemberDao;
import com.atguigu.gulimall.member.dao.MemberLevelDao;
import com.atguigu.gulimall.member.entity.MemberEntity;
import com.atguigu.gulimall.member.exception.PhoneExistException;
import com.atguigu.gulimall.member.exception.UsernameExistException;
import com.atguigu.gulimall.member.service.MemberService;
import com.atguigu.gulimall.member.vo.GiteeUserVo;
import com.atguigu.gulimall.member.vo.MemberRegisterVo;
import com.atguigu.gulimall.member.vo.MemberUserLoginVo;
import com.atguigu.gulimall.member.vo.SocialUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    @Resource
    MemberLevelDao memberLevelDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void regist(MemberRegisterVo registerVo) {
        MemberEntity entity = new MemberEntity();
        //获取会员的默认等级!
        Long memberLevel =  memberLevelDao.getDefaultLevel();
        entity.setLevelId(memberLevel);

        //检查手机号是否唯一!
        checkPhoneUnique(registerVo.getPhone());
        entity.setMobile(registerVo.getPhone());

        checkUserNameUnique(registerVo.getUserName());
        entity.setUsername(registerVo.getUserName());

        //密码要进行加密存储!
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encodePass = bCryptPasswordEncoder.encode(registerVo.getPassword());
        entity.setPassword(encodePass);

        entity.setCreateTime(new Date());
        entity.setNickname(registerVo.getUserName());

        //还有其他的信息,是用户注册后自己去完善的,不强求的字段
        baseMapper.insert(entity);
    }


    @Override
    public void checkPhoneUnique(String phone) throws PhoneExistException{
        Integer count = baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("mobile", phone));
        if (count > 0){
            throw new PhoneExistException();
        }
    }

    @Override
    public void checkUserNameUnique(String userName) throws UsernameExistException{
        Integer count = baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("username", userName));
        if (count > 0){
            throw new UsernameExistException();
        }
    }

    @Override
    public MemberEntity login(MemberUserLoginVo vo) {
        String loginacct = vo.getLoginacct();
        String password = vo.getPassword();

        //用手机号或者用户名登录,都是可以的!
        MemberEntity entity = baseMapper.selectOne(new QueryWrapper<MemberEntity>()
                .eq("username", loginacct).or().eq("mobile", loginacct));

        if (entity == null){
            return null;
        }else {
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            //用加密工具判断数据库的加密密码和表单密码是否能匹配上
            if(bCryptPasswordEncoder.matches(password, entity.getPassword())){
                return entity;
            }else {
                return null;
            }
        }
    }

    @Override
    public MemberEntity login(SocialUser socialUser) {
        //具有登录和注册合并的逻辑!

        //通过令牌信息获取gitee的个人信息
        GiteeUserVo giteeUser = getGiteeUserInfo(socialUser.getAccess_token());
        if (giteeUser != null){
            Long userId = giteeUser.getId();
            //1.判断当前社交登录的用户是否已经登录过!
            MemberEntity memberEntity = baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", userId));
            if (memberEntity != null){
                //以前使用过社交登录,这次登录就更新令牌就可以了
                MemberEntity updateEntity = new MemberEntity();
                updateEntity.setId(memberEntity.getId());
                updateEntity.setAccessToken(socialUser.getAccess_token());
                updateEntity.setExpiresIn(socialUser.getExpires_in());
                baseMapper.updateById(updateEntity);

                //修改完信息后,返回查询的用户信息
                memberEntity.setAccessToken(socialUser.getAccess_token());
                memberEntity.setExpiresIn(socialUser.getExpires_in());
                return memberEntity;
            }else {
                //没有查到社交用户的登录记录,因此我们需要给它创建一个账号
                MemberEntity register = new MemberEntity();

                register.setNickname(giteeUser.getName());
                register.setCreateTime(new Date());
                register.setLevelId(1L);
                //....
                register.setAccessToken(socialUser.getAccess_token());
                register.setSocialUid(userId.toString());
                register.setExpiresIn(socialUser.getExpires_in());

                //进行注册
                baseMapper.insert(register);

                return register;
            }
        }
        return null;
    }


    private GiteeUserVo getGiteeUserInfo(String accessToken){
        Map<String,String> map = new HashMap<>();
        map.put("access_token",accessToken);
        try {
            HttpResponse response = HttpUtils.doGet("https://gitee.com", "/api/v5/user", "GET", new HashMap<>(), map);
            if (response.getStatusLine().getStatusCode() == 200) {
                String bodyJson = EntityUtils.toString(response.getEntity());
                GiteeUserVo giteeUserVo = JSON.parseObject(bodyJson, GiteeUserVo.class);
                System.out.println("giteeUserVo = " + giteeUserVo);
                return giteeUserVo;
            }else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

